﻿////Movement_Trajectory_Analysis class file
////author: Przemysław Sobczyk, methods based on Ewelina Zemanek development
////Method description:
////Constructor:
////importing frame list and path and creating array of frames(name&path)
////get_color:
////importing listview and converting it to color array, constructing trajectory array (contains x,y coordinates of traced pixels)
////move_analysis:
////Main function tracking pixels, version not optimalized but without conditions;
////move_analysis_opt:
////Main function tracking pixels, version optimalized but with 3 safety conditions;
////draw:
////function wich draw a graph of pixel's coordinates (still in construction)
//////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;//zostawilem co by nie bylo errorow





namespace Movement_Trajectory_Analysis
{
    public class MTA
    {
        public static string[] frames;
        public static Color[] user_colors;
        public static int[,] trajectory;
        public static int[] sliced;
        Bitmap graph;
        public static int cheack = 0;
        public int correct = 0;
        public static int[] temp;
        

        //***********************************************************************
        public int tolerance = 30, margin = 5;//TOLERANCE AND MARGIN VALUES!!
        public int threadSleep = 24;
        //***********************************************************************
        public static int liczbaP;


        public void MTA_open(OpenFileDialog a)//class constructor wich gets frame lists
        {
            frames = new string[a.FileNames.Length];
            for (int i = 0; i < frames.Length; i++)
            {
                frames[i] = a.FileNames[i];
            }
            Bitmap temp = new Bitmap(frames[0]);
            graph = new Bitmap(temp.Width, temp.Height);
        }

        public MTA()
        {

        }

        public void get_color(ListView colors)// creating a user color array and settings first color coordinates
        {
            user_colors = new Color[colors.Items.Count];
            trajectory = new int[user_colors.Length * frames.Length, 2];
            for (int i = 0; i < colors.Items.Count; i++)
            {

                user_colors[i] = colors.Items[i].SubItems[0].BackColor;

                trajectory[i * frames.Length, 0] = Convert.ToInt32(colors.Items[i].SubItems[4].Text);
                trajectory[i * frames.Length, 1] = Convert.ToInt32(colors.Items[i].SubItems[5].Text);


            }




        }

        /////extream opt function methods
        public int cheackx(int x, Bitmap b)
        {
            if (x > 0)
            {
                if (x < b.Width)
                {
                    return x;
                }
                else
                    return b.Width;
            }
            else
                return 0;
        }
        public int cheacky(int y, Bitmap b)
        {
            if (y > 0)
            {
                if (y < b.Height)
                {
                    return y;
                }
                else
                    return b.Height;
            }
            else
                return 0;
        }
        /////***************************
        public int[,] move_analisis_opt_extream(System.ComponentModel.BackgroundWorker worker)//so damn awesome optimalized method!!
        {


            for (int h = 1; h < frames.Length; h++)//frame step
            {
                System.Threading.Thread.Sleep(threadSleep);
                worker.ReportProgress(h);

                Bitmap b = (Bitmap)Image.FromFile(frames[h]);
                for(int i=0; i < user_colors.Length; i++)
                //for (int i = 0; i < user_colors.Length; i++)//color step
                {
                    bool s = false;
                    cheack = 0;
                    for (int k = cheackx(trajectory[i * frames.Length + (h - 1), 0] - b.Width / margin, b); k < cheackx(trajectory[i * frames.Length + (h - 1), 0] + b.Width / margin, b); k++)
                    {
                        for (int j = cheacky(trajectory[i * frames.Length + (h - 1), 1] - b.Height / margin, b); j < cheacky(trajectory[i * frames.Length + (h - 1), 1] + b.Height / margin, b); j++)
                        {
                            if ((user_colors[i].R < b.GetPixel(k, j).R + tolerance) && (user_colors[i].R > b.GetPixel(k, j).R - tolerance) && (user_colors[i].G < b.GetPixel(k, j).G + tolerance) && (user_colors[i].G > b.GetPixel(k, j).G - tolerance) && (user_colors[i].B < b.GetPixel(k, j).B + tolerance) && (user_colors[i].B > b.GetPixel(k, j).B - tolerance))
                            {
                                s = true;
                                if (s == true)
                                {


                                    trajectory[i * frames.Length + h, 0] = k;
                                    trajectory[i * frames.Length + h, 1] = j;
                                    cheack = 1;
                                    liczbaP++;
                                    break;
                                }

                            }
                        }

                    }
                    if (cheack == 0)
                    {
                        trajectory[i * frames.Length + h, 0] = trajectory[i * frames.Length + h - 1, 0];
                        trajectory[i * frames.Length + h, 1] = trajectory[i * frames.Length + h - 1, 1];
                    }
                }
            }
            return trajectory;
        }


        public void draw(PictureBox s)
        {

            Graphics g = Graphics.FromImage(graph);
            g.FillRectangle(new SolidBrush(SystemColors.Control), 0, 0, graph.Width, graph.Height);
            for (int i = 0; i < user_colors.Length; i++)
            {
                for (int j = (i * frames.Length) + 1; j < ((i + 1) * frames.Length) - 1; j++)
                {
                    Pen line = new Pen(user_colors[i], 2);
                    if (trajectory[j - 1, 0] > 0 && trajectory[j - 1, 1] > 0 && trajectory[j, 0] > 0 && trajectory[j, 1] > 0)
                        g.DrawLine(line, trajectory[j - 1, 0], trajectory[j - 1, 1], trajectory[j, 0], trajectory[j, 1]);
                }

            }
            s.Image = graph;
        }

        //Threading:
        public int[] move_analisis_opt_extream_Threading()
        {
            switch (user_colors.Length)
            {
                case 1:
                    {
                        Thread T1 = new Thread(MTA_method);
                        T1.Start(0);
                        break;
                    }
                case 2:
                    {
                        Thread T1 = new Thread(MTA_method);
                        Thread T2 = new Thread(MTA_method);
                        T1.Start(0);
                        T2.Start(1);

                        break;
                    }
                case 3:
                    {
                        Thread T1 = new Thread(MTA_method);
                        Thread T2 = new Thread(MTA_method);
                        Thread T3 = new Thread(MTA_method);
                        T1.Start(0);
                        T2.Start(1);
                        T3.Start(2);

                        break;
                    }
                case 4:
                    {
                        Thread T1 = new Thread(MTA_method);
                        Thread T2 = new Thread(MTA_method);
                        Thread T3 = new Thread(MTA_method);
                        Thread T4 = new Thread(MTA_method);
                        T1.Start(0);
                        T2.Start(1);
                        T3.Start(2);
                        T4.Start(3);

                        break;
                    }
                case 6:
                    {
                        Thread T1 = new Thread(MTA_method);
                        Thread T2 = new Thread(MTA_method);
                        Thread T3 = new Thread(MTA_method);
                        Thread T4 = new Thread(MTA_method);
                        Thread T5 = new Thread(MTA_method);
                        Thread T6 = new Thread(MTA_method);
                        T1.Start(0);
                        T2.Start(1);
                        T3.Start(2);
                        T4.Start(3);
                        T5.Start(4);
                        T6.Start(5);


                        break;
                    }
            }

          table_slice(trajectory);
          return temp;
        }
        public void MTA_method(object numer)
        {
            int nr = (int)numer;
            for (int h = 1; h < frames.Length; h++)//frame step
            {

                    Bitmap b = (Bitmap)Image.FromFile(frames[h]);                        
                    bool s = false;
                    cheack = 0;
                    for (int k = cheackx(trajectory[nr * frames.Length + (h - 1), 0] - b.Width / margin, b); k < cheackx(trajectory[nr * frames.Length + (h - 1), 0] + b.Width / margin, b); k++)
                    {
                        for (int j = cheacky(trajectory[nr * frames.Length + (h - 1), 1] - b.Height / margin, b); j < cheacky(trajectory[nr * frames.Length + (h - 1), 1] + b.Height / margin, b); j++)
                        {
                            if ((user_colors[nr].R < b.GetPixel(k, j).R + tolerance) && (user_colors[nr].R > b.GetPixel(k, j).R - tolerance) && (user_colors[nr].G < b.GetPixel(k, j).G + tolerance) && (user_colors[nr].G > b.GetPixel(k, j).G - tolerance) && (user_colors[nr].B < b.GetPixel(k, j).B + tolerance) && (user_colors[nr].B > b.GetPixel(k, j).B - tolerance))
                            {
                                s = true;
                                if (s == true)
                                {


                                    trajectory[nr * frames.Length + h, 0] = k;
                                    trajectory[nr * frames.Length + h, 1] = j;
                                    cheack = 1;
                                    liczbaP++;
                                    break;
                                }

                            }
                        }

                    }
                    if (cheack == 0)
                    {
                        trajectory[nr * frames.Length + h, 0] = trajectory[nr * frames.Length + h - 1, 0];
                        trajectory[nr * frames.Length + h, 1] = trajectory[nr * frames.Length + h - 1, 1];
                    }
                
            }
            
        }

        public void table_slice(int [,] trajectory) 
        {
            int k = 0;
            sliced=new int[2*user_colors.Length*frames.Length];
            
            for (int j = 0; j< user_colors.Length; j++)
            {
                for (int i = j ; i < user_colors.Length * frames.Length; i += user_colors.Length)
                {
                    sliced[k] = trajectory[i, 0];
                    sliced[k + 1] = trajectory[i, 1];
                    k += 2;
                    
                }
            }
            
            temp = new int[sliced.Length + 2];
            temp[0] = correct;
            temp[temp.Length - 1] = 1;
            for (int i = 1; i < temp.Length - 1; i++)
            {
                temp[i] = sliced[i - 1];
            }
           
        }
    }
    
}
